#include <string>
#include <filesystem>
#include "../../include/utils/common_utils.h"
#include "../../include/utils/string_util.h"
#ifdef _WIN32
#include <windows.h>
typedef DWORD pid_t;
return GetCurrentProcessId();
#else
#include<unistd.h>
#endif


CommonUtils::CommonUtils()
{}
std::string CommonUtils::getEnv(const std::string &key, const std::string &defaultValue)
{
    char *value = getenv(key.c_str());
    if (value)
    {
        return value;
    }
    return defaultValue;
}
void CommonUtils::setEnv(const std::string &key, const std::string &value, bool replace/* = true*/)
{
    setenv(key.c_str(), value.c_str(), replace ? 1 : 0);
}
bool CommonUtils::parserHostPort(const std::string &callerApi, std::string &host, int &port)
{
    auto index = callerApi.find("://");
    if (index == std::string::npos)
    {
        return false;
    }
    host = callerApi.substr(index + 3);

    index = host.find(":");
    if (index == std::string::npos)
    {
        return false;
    }
    std::string portStr = host.substr(index + 1);
    host = host.substr(0, index);
    port = std::stoi(portStr);
    return true;
}
pid_t CommonUtils::getCurrentPid()
{
#ifdef _WIN32
    return GetCurrentProcessId();
#else
    return getpid();
#endif
    return 0;
}
std::string CommonUtils::splitFirstNameSpace(const std::string &key)
{
    std::vector<std::string> split = utils::StringUtil::split(key, "/", utils::SplitBehavior::SkipEmptyParts);
    if (split.empty())
    {
        return key;
    }
    return "/" + split.at(0);
}
std::string CommonUtils::removeBias(const std::string &str)
{
    std::string result = str;
    while (utils::StringUtil::contains(result, "//"))
    {
        result = utils::StringUtil::replace(result, "//", "/");
    }
    return result;
}

std::string CommonUtils::generateNameSpace(const std::string &name)
{
    if (name.empty())
    {
        return "/";
    }
    std::string ns;
    if (name.at(0) == '/')
    {
        ns = name;
    }
    else
    {
        ns = "/" + name;
    }
    ns = utils::StringUtil::trimRight(ns, "/");
    return ns;
}
std::vector<std::string> CommonUtils::getRootPackagePath()
{
    const std::string &path = getEnv("ROS_PACKAGE_PATH", "./");
    return utils::StringUtil::split(path, ":", utils::SplitBehavior::SkipEmptyParts);
}
std::vector<std::string> CommonUtils::getPackagePath(const std::string &package)
{
    std::vector<std::string> packagePathList;
    std::vector<std::string> rootPackagePathList = getRootPackagePath();
    for (const auto &path: rootPackagePathList)
    {
        std::filesystem::path packagePath(path);
        packagePath = packagePath / package;
        if (std::filesystem::exists(packagePath))//目录存在，则认为包存在
        {
            packagePathList.push_back(packagePath.string());
        }
    }
    return packagePathList;
}
std::vector<std::string> CommonUtils::getLaunchPath(const std::string &package, const std::string &launchName)
{
    std::vector<std::string> launchFilePath;
    std::vector<std::string> packagePathList = CommonUtils::getPackagePath(package);
    for (const auto &packagePath: packagePathList)
    {
        std::filesystem::path path(packagePath);
        std::filesystem::path launchPath = path / "launch" / std::filesystem::path(launchName);
        launchFilePath.push_back(launchPath.string());
    }
    return launchFilePath;
}
std::vector<std::string> CommonUtils::getExecPath(const std::string &package, const std::string &name)
{
    std::vector<std::string> execFilePath;
    std::vector<std::string> packagePathList = getPackagePath(package);
    for (const auto &packagePath: packagePathList)
    {
        std::filesystem::path path(packagePath);//share/pkg
        path = path.parent_path().parent_path();
        std::filesystem::path execPath = path / "lib" / std::filesystem::path(package) / std::filesystem::path(name);
        execFilePath.push_back(execPath.string());
    }
    return execFilePath;
}
